package com.beiing.leafchat;


import com.beiing.leafchat.bean.AxisValue;
import com.beiing.leafchat.bean.Line;
import com.beiing.leafchat.bean.PointValue;
import com.beiing.leafchat.renderer.OutsideLineRenderer;
import com.beiing.leafchat.support.LeafUtil;
import com.beiing.leafchat.support.Mode;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ScrollHelper;
import ohos.agp.render.Canvas;
import ohos.app.Context;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;

import java.util.List;

/**
 * Created by chenliu on 2017/1/12.<br/>
 * 描述： to be continued
 * </br>
 */

public class OutsideLineChart extends AbsLeafChart implements Component.ScrolledListener {

    private Line line;

    private OutsideLineRenderer outsideLineRenderer;

    /**
     * mMove为偏移量
     */
    private int mLastX;
    private int mMove = 0;
    /**
     * 两个点之间间 隔
     **/
    private int mStep;

    /**
     * 滑动到第一个点或最后一个点时，还能继续滑动的距离
     **/
    private int maxOverMove;

    private ScrollHelper mScroller;

    private GestureDetector gestureDetector;

    public OutsideLineChart(Context context) {
        this(context, null, "0");
    }

    public OutsideLineChart(Context context, AttrSet attrs) {
        this(context, attrs, "0");
    }

    public OutsideLineChart(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
//        mScroller = new Scroller(getContext());
        mScroller = new ScrollHelper();
        gestureDetector = new GestureDetector(new SimpleGestureListener());
        maxOverMove = (int) LeafUtil.dp2px(mContext, 100);
        setTouchEventListener(new TouchEventListener() {
            @Override
            public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
                gestureDetector.onTouchEvent(touchEvent);
                MmiPoint point = touchEvent.getPointerPosition(touchEvent.getIndex());
                int xPosition = (int) point.getX();
                switch (touchEvent.getAction()) {
                    case TouchEvent.PRIMARY_POINT_DOWN:
                        mScroller.abortAnimation();
                        mLastX = xPosition;
                        break;
                    case TouchEvent.PRIMARY_POINT_UP:
                        if (mMove > 0) {
                            smoothScrollTo(startMarginX, 0);
                        } else if (mMove <= -getMinMove()) {
                            smoothScrollTo(-getMinMove(), 0);
                        }
                        break;
                    case TouchEvent.POINT_MOVE:
                        if (mMove >= 0 && mMove <= maxOverMove || mMove <= 0 && mMove >= -getMinMove()) {
                            smoothScrollBy(xPosition - mLastX, 0);
                        }
                        break;
                    default:
                        break;
                }
                mLastX = xPosition;
                return true;
            }
        });
    }

    @Override
    protected void initAttrs(AttrSet attrs) {
        super.initAttrs(attrs);
        mStep = (int) LeafUtil.dp2px(mContext, 30);
    }

//    @Override
//    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//        super.onSizeChanged(w, h, oldw, oldh);
//    }

    @Override
    protected void initRenderer() {
        outsideLineRenderer = new OutsideLineRenderer(mContext, this);
    }

    @Override
    protected void setRenderer() {
        super.setRenderer(outsideLineRenderer);
    }

    @Override
    protected void resetPointWeight() {
        if (line != null) {
            super.resetPointWeight(line);
        }
    }

    @Override
    protected void resetAsixX() {
        if (axisX != null) {
            List<AxisValue> values = axisX.getValues();
            int sizeX = values.size(); //几条y轴
            float xStep = mStep;
            for (int i = 0; i < sizeX; i++) {
                AxisValue axisValue = values.get(i);
                axisValue.setPointY(mHeight);
                if (i == 0) {
                    axisValue.setPointX(leftPadding + startMarginX);
                } else {
                    axisValue.setPointX(leftPadding + startMarginX + (int) xStep * i);
                }
            }
            switch (coordinateMode) {
                case Mode.ACROSS:
                case Mode.X_ACROSS:
                    axisX.setStartX(leftPadding * 0.5f);
                    break;

                case Mode.INTERSECT:
                case Mode.Y_ACROSS:
                    axisX.setStartX(leftPadding);
                    break;
            }
            axisX.setStartY(mHeight - bottomPadding).setStopX(mWidth).setStopY(mHeight - bottomPadding);
        }
    }

    @Override
    public void invalidate() {
        super.invalidate();
        addDrawTask(this::onDraw);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        System.out.println("===mScroller=" + mScroller.getCurrValue(0) + "=" + mScroller.getCurrValue(1) + "=" + mScroller.getCurrValue(2) + "=" + mScroller.getCurrValue(3));
        System.out.println("===onDraw");
        super.onDraw(component, canvas);
        outsideLineRenderer.drawCoordinateLines(canvas, axisX, axisY);
        outsideLineRenderer.drawCoordinateText(canvas, axisX, axisY, mMove);

        if (line != null) {
            outsideLineRenderer.drawLines(canvas, line, axisY, mMove);

            if (line.isFill()) {
                //填充
                outsideLineRenderer.drawFillArea(canvas, line, axisX, mMove);
            }

            outsideLineRenderer.drawPoints(canvas, line, axisY, mMove);
        }

        if (line != null && line.isHasLabels()) {
            outsideLineRenderer.drawLabels(canvas, line, axisY, mMove);
        }
    }


    //调用此方法设置滚动的相对偏移
    public void smoothScrollBy(int dx, int dy) {
        System.out.println("===getScrollDistanceX=" + mScroller.getScrollDistanceX() + " getScrollDistanceY=" + mScroller.getScrollDistanceY() + " dx=" + dx + " dy=" + dy);
        //设置mScroller的滚动偏移量
        mScroller.startScroll(+mScroller.getScrollDistanceX(), mScroller.getScrollDistanceY(), dx, dy);
        invalidate();//这里必须调用invalidate()才能保证computeScroll()会被调用，否则不一定会刷新界面，看不到滚动效果
    }

    //调用此方法滚动到目标位置
    public void smoothScrollTo(int fx, int fy) {
        int dx = fx - mScroller.getScrollDistanceX();
        int dy = fy - mScroller.getScrollDistanceY();
        smoothScrollBy(dx, dy);
    }


    @Override
    public void onContentScrolled(Component component, int i, int i1, int i2, int i3) {
        System.out.println("===onContentScrolled=" + i + "=" + i1 + "=" + -i2 + "=" + i3);
    }

    //    @Override
//    public void computeScroll() {
//        if (mScroller.computeScrollOffset()) {
//            //判断左右边界
//            mMove = mScroller.getCurrX();
//            postInvalidate();
//        }
//    }
//

    @Override
    public void addScrolledListener(ScrolledListener listener) {
        System.out.println("======ScrolledListener=");
        super.addScrolledListener(listener);
    }

    private class SimpleGestureListener implements GestureDetector.OnGestureListener {

        @Override
        public boolean onScroll(TouchEvent e1, TouchEvent e2, float distanceX, float distanceY) {
            int minMove;
            minMove = getMinMove();

            mScroller.doFling(mMove, 0, (int) distanceX, (int) distanceY, -minMove, startMarginX, 0, 0);
            return true;
        }
    }


    private int getMinMove() {
        int minMove = Integer.MIN_VALUE;
        if (line != null) {
            List<PointValue> values = line.getValues();
            if (values != null && values.size() > 0) {
                PointValue pointValue = values.get(values.size() - 1);
                minMove = (int) pointValue.getOriginX() - mWidth + maxOverMove;
            }
        }
        return minMove;
    }

    /**
     * 带动画的绘制
     *
     * @param duration
     */
    public void showWithAnimation(int duration) {
        outsideLineRenderer.showWithAnimation(duration);
    }

    public void show() {
        showWithAnimation(0);
    }

    public void setChartData(Line chartData) {
        line = chartData;
        resetPointWeight();
    }

    public Line getChartData() {
        return line;
    }
}
